package j.util.jdbc.simple.core;

import j.util.New;
import j.util.StringUtils;
import j.util.jdbc.simple.core.operations.SimpleJdbcDeleteOperations;
import j.util.jdbc.simple.core.support.SimpleJdbcUtils;
import j.util.jdbc.simple.metadata.Column;
import j.util.jdbc.simple.metadata.TableMetaData;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * jdbc的删除操作
 * @author 刘军海
 * @version Sep 14, 2011 10:17:39 AM
 */
public class SimpleJdbcDelete extends SimpleJdbcAbstract implements SimpleJdbcDeleteOperations {

	/**
	 * 根据PK执行删除操作
	 */
	@Override
	public <T> int delete(Connection connection,Class<T> clazz,Map<String,Object> args) throws SQLException {
		SQLData sd = getSqlData(clazz);
		SQLForDelete delSql = sd.getSqlDelete();
		String sql = delSql.getDeleteSql();
		if(StringUtils.isNullOrEmpty(sql)){
			throw new RuntimeException("entity delete must specify entity's pk columns.");
		}
		List<String> order = delSql.getDeleteOrder();
		//先查出待删除节点的左右值
		int lft,rgt;
		TableMetaData tmd = sd.getTmd();
		String _sql = String.format("select %s,%s from %s where %s=?",
				tmd.getLeftFieldName(),tmd.getRightFieldName(),tmd.getTableName(),tmd.getPkColumns());
		int ret = 0;
		if(tmd.isTree()) {
			log.debug(String.format("%s是树表，需要正确处理左右值。",tmd.getTableName()));
			boolean isAutocommit = false;
			if (connection.getAutoCommit()) {
				isAutocommit = true;
				connection.setAutoCommit(false);
			}
			PreparedStatement pstmt = connection.prepareStatement(_sql);
			pstmt.setString(1, String.valueOf(args.get(tmd.getPkColumns())));
			ResultSet rs = pstmt.executeQuery();
			if (rs.next()) {
				lft = rs.getInt(1);
				rgt = rs.getInt(2);
				log.debug(String.format("获取到删除的节点的左值为%s,右值为%s，在删除的同时并更新所有大于左值的节点的左值-2，大于右值的节点的右值-2",
						lft,rgt));
				//update usr_dept set lft=lft-2 where lft>7;
				//update usr_dept set rgt=rgt-2 where rgt>8;
				ret = executeSql(connection, sd.getTmd().getColumns(), sql, args, order);
				_sql = String.format("update %s set %s=%s-2 where %s>?;update %s set %s=%s-2 where %s>?;",
						tmd.getTableName(), tmd.getLeftFieldName(), tmd.getLeftFieldName(), tmd.getLeftFieldName(),
						tmd.getTableName(), tmd.getRightFieldName(), tmd.getRightFieldName(), tmd.getRightFieldName());
				pstmt = connection.prepareStatement(_sql);
				pstmt.setInt(1, lft);
				pstmt.setInt(2, rgt);
				pstmt.execute();
				rs.close();
				pstmt.close();
				if (isAutocommit) {
					connection.commit();
				}
			} else {
				throw new SQLException("参数为【" + args + "】的记录没找到！");
			}
		}else{
			ret = executeSql(connection, sd.getTmd().getColumns(), sql, args, order);
		}
		return ret;
	}
	private int executeSql(Connection connection,Map<String,Column> columns,String sql,Map<String,Object> args,List<String> argsOrder) throws SQLException{
		PreparedStatement stmt = null;
        stmt = connection.prepareStatement(sql);
        //设置参数
        SimpleJdbcUtils.setPreapredStatementParameters(columns, stmt, argsOrder, args);
        log.info("execute delete sql:"+sql+" with values:"+args);
        int ret = stmt.executeUpdate();
        stmt.close();
        return ret;
	}
	@Override
	public <T> int deleteByCW(Connection connection,Class<T> clazz, Map<String,Object> args)throws SQLException{
		SQLData sd = getSqlData(clazz);
		SQLForDelete delSql = sd.getSqlDelete();
		List<String> order = New.list();
		String sql = delSql.generateDelSqlByCW(args,order);
		if(StringUtils.isNullOrEmpty(sql)){
			throw new RuntimeException("deleteByEntityAttribute must specify entity's not null attribute at least one.");
		}
		return executeSql(connection,sd.getTmd().getColumns(),sql,args,order);
	}

	@Override
	public <T> int[] deleteBatch(Connection connection,Class<T> clazz,List<Map<String,Object>> list)throws SQLException{
		int rets[] = new int[list.size()];
		SQLData sd = getSqlData(clazz);
		SQLForDelete delSql = sd.getSqlDelete();
		String sql = delSql.getDeleteSql();
		if(StringUtils.isNullOrEmpty(sql)){
			throw new RuntimeException("entity delete must specify entity's pk columns.");
		}
		List<String> order = delSql.getDeleteOrder();
		Map<String,Column> columns = sd.getTmd().getColumns();
		PreparedStatement stmt = null;
		log.info("begin delete batch with sql:"+sql+".");
        stmt = connection.prepareStatement(sql);
        for(int i=0;i<list.size();i++){
            //设置参数
            Map<String,Object> args = list.get(i);
            SimpleJdbcUtils.setPreapredStatementParameters(columns, stmt, order, args);
            stmt.addBatch();
            log.info(StringUtils.format("add delete to batch, with values:{1}.", args));
        }
        rets = stmt.executeBatch();
        log.info("executebatch succussed.");
        stmt.close();
		return rets;
	}

}
